package com.ruoyi.ai.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;

/**
 * @author: Coach Tam
 * @since: 2024/4/18 14:35
 * @values: 坚持灵活 灵活坚持
 */
@Slf4j
@RestController
public class NoneBlockingController {

    //模拟从数据库查询用户信息，耗时5秒
    Supplier<String> usernameSupplier = () -> {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return "张三";
    };

    //模拟从数据库查询用户分数，耗时5秒
    Supplier<Integer> scoreSupplier = () -> {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return 80;
    };

    /**
     * 阻塞接口，模拟从数据库查询用户信息和分数，耗时10秒以上
     * @return
     */
    @GetMapping("/blocking")
    public String blocking()  {
        log.info("blocking start");
        String username = usernameSupplier.get();
        Integer score = scoreSupplier.get();
        log.info("blocking end");
        return username+":"+score;
    }

    /**
     * 非阻塞接口，模拟从数据库查询用户信息和分数，耗时10秒以内
     */
    @GetMapping("/nonblocking")
    public Mono<String> nonblocking() {
        log.info("nonblocking start");
        // 创建了一个供应商发布在有界弹性调度器上的用户名Mono
        Mono<String> usernameMono = Mono.fromSupplier(usernameSupplier).publishOn(Schedulers.boundedElastic());
        // 创建了一个供应商发布在有界弹性调度器上的分数Mono
        Mono<Integer> scoreMono = Mono.fromSupplier(scoreSupplier).publishOn(Schedulers.boundedElastic());
        // 使用zip操作将用户名Mono和分数Mono进行合并，并映射成一个新的Mono
        Mono<String> result = Mono.zip(usernameMono, scoreMono).map(tuple -> tuple.getT1() + ":" + tuple.getT2());
        log.info("nonblocking end");
        return result;
    }

}
